package com.example.opengldemo._06_;

import android.opengl.GLES30;

import com.example.opengldemo.util.MatrixState;
import com.example.opengldemo.util.ShaderUtil;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.util.ArrayList;

public class Ball {

    String vertexRes  = "sun/vertex.sh";
    String fragmentRes  = "sun/fragment.sh";

    int mProgram ;

    int m_A_PositionHandle ;
    int m_A_ColorHandle ;
    int m_U_MVPMatrixHandle ;
    int m_U_MMatrixHandle;
    int m_U_RHandle ;
    int m_A_NormalHandle;
    int m_A_LightLocationHandle;
    int m_U_CameraLocationHandle;
    int m_U_LightDirectionHandle;


    FloatBuffer vertaxBuffer ;
    FloatBuffer fragBuffer ;
    FloatBuffer mNormalBuffer;

    int vCount ;

    float xAngle ;
    float yAngle ;
    float zAngle ;

    float r = 0.8f;

    final float UNIT_SIZE = 0.2f;
    Ball(_6MySurfaceView view){
        initBufferData();
        initHandle(view) ;
    }

    private void initHandle(_6MySurfaceView view) {
        mProgram = ShaderUtil.createProgram(
                ShaderUtil.loadFromAssetsFile(vertexRes , view.getResources()) ,
                ShaderUtil.loadFromAssetsFile(fragmentRes , view.getResources())
        );

        m_A_PositionHandle = GLES30.glGetAttribLocation(mProgram , "aPosition");
        m_A_ColorHandle = GLES30.glGetAttribLocation(mProgram , "aColor");
        m_U_MVPMatrixHandle = GLES30.glGetUniformLocation(mProgram , "uMVPMatrix");
        m_U_MMatrixHandle = GLES30.glGetUniformLocation(mProgram , "uMMatrix"); //世界空间的位置

        m_A_NormalHandle = GLES30.glGetAttribLocation(mProgram, "aNormal");
        m_A_LightLocationHandle=GLES30.glGetUniformLocation(mProgram, "uLightLocation");
        m_U_CameraLocationHandle = GLES30.glGetUniformLocation(mProgram , "uCamera");
        m_U_LightDirectionHandle=GLES30.glGetUniformLocation( mProgram, "uLightDirection");

        m_U_RHandle = GLES30.glGetUniformLocation(mProgram , "uR") ;
    }

    private void initBufferData() {
        float[] vertexArray = getCubeData();
        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(vertexArray.length * 4);
        byteBuffer.order(ByteOrder.nativeOrder());
        vertaxBuffer = byteBuffer.asFloatBuffer();
        vertaxBuffer.put(vertexArray);
        vertaxBuffer.position(0);

        float[] colorArray = getFragData();
        byteBuffer = ByteBuffer.allocateDirect(colorArray.length * 4);
        byteBuffer.order(ByteOrder.nativeOrder());
        fragBuffer = byteBuffer.asFloatBuffer();
        fragBuffer.put(colorArray);
        fragBuffer.position(0);

        byteBuffer = ByteBuffer.allocateDirect(vertexArray.length*4);
        byteBuffer.order(ByteOrder.nativeOrder());
        mNormalBuffer = byteBuffer.asFloatBuffer();
        mNormalBuffer.put(getNormal());
        mNormalBuffer.position(0);

    }

    private float[] getBallData() {
        ArrayList<Float> alVertix = new ArrayList<Float>();
        final int angleSpan = 10;
        for (int vAngle = -90; vAngle < 90; vAngle = vAngle + angleSpan){

            for (int hAngle = 0; hAngle <= 360; hAngle = hAngle + angleSpan){
                float x0 = (float) (r * UNIT_SIZE* Math.cos(Math.toRadians(vAngle)) * Math.cos(Math.toRadians (hAngle)));
                float y0 = (float) (r * UNIT_SIZE * Math.cos(Math.toRadians(vAngle)) * Math.sin(Math.toRadians (hAngle)));
                float z0 = (float) (r * UNIT_SIZE * Math.sin(Math.toRadians(vAngle)));

                float x1 = (float) (r * UNIT_SIZE* Math.cos(Math.toRadians(vAngle))
                        * Math.cos(Math.toRadians(hAngle + angleSpan)));

                float y1 = (float) (r * UNIT_SIZE* Math.cos(Math.toRadians(vAngle))
                        * Math.sin(Math.toRadians(hAngle + angleSpan)));
                float z1 = (float) (r * UNIT_SIZE * Math.sin(Math.toRadians(vAngle)));

                float x2 = (float) (r * UNIT_SIZE* Math.cos(Math.toRadians(vAngle + angleSpan))* Math.cos(Math.toRadians(hAngle + angleSpan)));

                float y2 = (float) (r * UNIT_SIZE* Math.cos(Math.toRadians(vAngle + angleSpan)) * Math.sin(Math.toRadians(hAngle + angleSpan)));

                float z2 = (float) (r * UNIT_SIZE * Math.sin(Math.toRadians(vAngle + angleSpan)));

                float x3 = (float) (r * UNIT_SIZE* Math.cos(Math.toRadians(vAngle +
                        angleSpan))* Math.cos(Math.toRadians(hAngle)));

                float y3 = (float) (r * UNIT_SIZE* Math.cos(Math.toRadians(vAngle + angleSpan))
                        * Math.sin(Math.toRadians(hAngle)));

                float z3 = (float) (r * UNIT_SIZE * Math.sin(Math.toRadians(vAngle + angleSpan)));

                alVertix.add(x1); alVertix.add(y1); alVertix.add(z1);
                alVertix.add(x3); alVertix.add(y3); alVertix.add(z3);
                alVertix.add(x0); alVertix.add(y0); alVertix.add(z0);
                alVertix.add(x1); alVertix.add(y1); alVertix.add(z1);
                alVertix.add(x2); alVertix.add(y2); alVertix.add(z2);
                alVertix.add(x3); alVertix.add(y3); alVertix.add(z3);

            } }

        vCount = alVertix.size() / 3;
        float vertices[] = new float[vCount * 3];

        for (int i = 0; i < alVertix.size(); i++) {
            vertices[i] = alVertix.get(i);
        }
        return vertices ;
    }

    private float[] getFragData() {
        float[] colorArray = new float[vCount * 4];//顶点着色数据的初始化
        for (int i = 0; i < vCount; i++) {
            if (i % 3 == 0) { //中心点为白色，RGBA 4 个通道[1,1,1,0]
                colorArray[i * 4] = 1;
                colorArray[i * 4 + 1] = 1;
                colorArray[i * 4 + 2] = 1;
                colorArray[i * 4 + 3] = 0;
            } else { //边上的点为淡蓝色，RGBA 4 个通道[0.45,0.75,0.75,0]
                colorArray[i * 4] = 0.45f;
                colorArray[i * 4 + 1] = 0.75f;
                colorArray[i * 4 + 2] = 0.75f;
                colorArray[i * 4 + 3] = 0;
            }
        }
        return colorArray;
    }


    public void drawSelf(){
        GLES30.glUseProgram(mProgram);
        MatrixState.rotate(xAngle, 1, 0, 0);
        MatrixState.rotate(yAngle, 0, 1, 0);
        MatrixState.rotate(zAngle, 0, 0, 1);
        GLES30.glUniform1f(m_U_RHandle, r * UNIT_SIZE);//将半􏱋属性传入渲染管线
        GLES30.glUniformMatrix4fv(m_U_MVPMatrixHandle , 1 , false , MatrixState.getFinalMatrix() , 0);
        GLES30.glUniformMatrix4fv(m_U_MMatrixHandle , 1 , false , MatrixState.getMMatrix() , 0);
        GLES30.glUniform3fv(m_U_CameraLocationHandle, 1, MatrixState.cameraLocationFB);
        GLES30.glVertexAttribPointer(m_A_PositionHandle , 3 , GLES30.GL_FLOAT , false , 3*4 , vertaxBuffer);
        GLES30.glVertexAttribPointer(m_A_ColorHandle , 4 , GLES30.GL_FLOAT , false , 4*4 , fragBuffer);
        GLES30.glUniform3fv( m_A_LightLocationHandle , 1, MatrixState.lightLocationFB);
        GLES30.glUniform3fv( //将定向光方向数据传入渲染管线
                m_U_LightDirectionHandle, 1, MatrixState.lightDirectionFB);
        GLES30.glVertexAttribPointer(m_A_NormalHandle, 3, GLES30.GL_FLOAT, false,3 * 4, mNormalBuffer);
        GLES30.glEnableVertexAttribArray(m_A_ColorHandle);
        GLES30.glEnableVertexAttribArray(m_A_PositionHandle);
        GLES30.glEnableVertexAttribArray(m_A_NormalHandle);

        GLES30.glDrawArrays(GLES30.GL_TRIANGLES , 0  ,vCount );

        GLES30.glDisableVertexAttribArray(m_A_PositionHandle);
        GLES30.glDisableVertexAttribArray(m_A_ColorHandle);
        GLES30.glDisableVertexAttribArray(m_A_NormalHandle);

    }


    public float[] getCubeData(){
        vCount=12*6;
        final float UNIT_SIZE = 0.2f ;
        return new float[]
                {
                        //«∞√Ê
                        0,0,UNIT_SIZE,
                        UNIT_SIZE,UNIT_SIZE,UNIT_SIZE,
                        -UNIT_SIZE,UNIT_SIZE,UNIT_SIZE,
                        0,0,UNIT_SIZE,
                        -UNIT_SIZE,UNIT_SIZE,UNIT_SIZE,
                        -UNIT_SIZE,-UNIT_SIZE,UNIT_SIZE,
                        0,0,UNIT_SIZE,
                        -UNIT_SIZE,-UNIT_SIZE,UNIT_SIZE,
                        UNIT_SIZE,-UNIT_SIZE,UNIT_SIZE,
                        0,0,UNIT_SIZE,
                        UNIT_SIZE,-UNIT_SIZE,UNIT_SIZE,
                        UNIT_SIZE,UNIT_SIZE,UNIT_SIZE,

                        0,0,-UNIT_SIZE,
                        UNIT_SIZE,UNIT_SIZE,-UNIT_SIZE,
                        UNIT_SIZE,-UNIT_SIZE,-UNIT_SIZE,
                        0,0,-UNIT_SIZE,
                        UNIT_SIZE,-UNIT_SIZE,-UNIT_SIZE,
                        -UNIT_SIZE,-UNIT_SIZE,-UNIT_SIZE,
                        0,0,-UNIT_SIZE,
                        -UNIT_SIZE,-UNIT_SIZE,-UNIT_SIZE,
                        -UNIT_SIZE,UNIT_SIZE,-UNIT_SIZE,
                        0,0,-UNIT_SIZE,
                        -UNIT_SIZE,UNIT_SIZE,-UNIT_SIZE,
                        UNIT_SIZE,UNIT_SIZE,-UNIT_SIZE,

                        -UNIT_SIZE,0,0,
                        -UNIT_SIZE,UNIT_SIZE,UNIT_SIZE,
                        -UNIT_SIZE,UNIT_SIZE,-UNIT_SIZE,
                        -UNIT_SIZE,0,0,
                        -UNIT_SIZE,UNIT_SIZE,-UNIT_SIZE,
                        -UNIT_SIZE,-UNIT_SIZE,-UNIT_SIZE,
                        -UNIT_SIZE,0,0,
                        -UNIT_SIZE,-UNIT_SIZE,-UNIT_SIZE,
                        -UNIT_SIZE,-UNIT_SIZE,UNIT_SIZE,
                        -UNIT_SIZE,0,0,
                        -UNIT_SIZE,-UNIT_SIZE,UNIT_SIZE,
                        -UNIT_SIZE,UNIT_SIZE,UNIT_SIZE,
                        //”“√Ê
                        UNIT_SIZE,0,0,
                        UNIT_SIZE,UNIT_SIZE,UNIT_SIZE,
                        UNIT_SIZE,-UNIT_SIZE,UNIT_SIZE,
                        UNIT_SIZE,0,0,
                        UNIT_SIZE,-UNIT_SIZE,UNIT_SIZE,
                        UNIT_SIZE,-UNIT_SIZE,-UNIT_SIZE,
                        UNIT_SIZE,0,0,
                        UNIT_SIZE,-UNIT_SIZE,-UNIT_SIZE,
                        UNIT_SIZE,UNIT_SIZE,-UNIT_SIZE,
                        UNIT_SIZE,0,0,
                        UNIT_SIZE,UNIT_SIZE,-UNIT_SIZE,
                        UNIT_SIZE,UNIT_SIZE,UNIT_SIZE,

                        0,UNIT_SIZE,0,
                        UNIT_SIZE,UNIT_SIZE,UNIT_SIZE,
                        UNIT_SIZE,UNIT_SIZE,-UNIT_SIZE,
                        0,UNIT_SIZE,0,
                        UNIT_SIZE,UNIT_SIZE,-UNIT_SIZE,
                        -UNIT_SIZE,UNIT_SIZE,-UNIT_SIZE,
                        0,UNIT_SIZE,0,
                        -UNIT_SIZE,UNIT_SIZE,-UNIT_SIZE,
                        -UNIT_SIZE,UNIT_SIZE,UNIT_SIZE,
                        0,UNIT_SIZE,0,
                        -UNIT_SIZE,UNIT_SIZE,UNIT_SIZE,
                        UNIT_SIZE,UNIT_SIZE,UNIT_SIZE,

                        0,-UNIT_SIZE,0,
                        UNIT_SIZE,-UNIT_SIZE,UNIT_SIZE,
                        -UNIT_SIZE,-UNIT_SIZE,UNIT_SIZE,
                        0,-UNIT_SIZE,0,
                        -UNIT_SIZE,-UNIT_SIZE,UNIT_SIZE,
                        -UNIT_SIZE,-UNIT_SIZE,-UNIT_SIZE,
                        0,-UNIT_SIZE,0,
                        -UNIT_SIZE,-UNIT_SIZE,-UNIT_SIZE,
                        UNIT_SIZE,-UNIT_SIZE,-UNIT_SIZE,
                        0,-UNIT_SIZE,0,
                        UNIT_SIZE,-UNIT_SIZE,-UNIT_SIZE,
                        UNIT_SIZE,-UNIT_SIZE,UNIT_SIZE,
                };

    }



    public float[] getNormal() {
        return new float[]{
                0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1,//前面上6个顶点的法向量
                0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1,//后面上6个顶点的法向量
                -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0,//左面上6个顶点的法向量
                1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, //右面上 6 个顶点的法向量
                0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, //上面上 6 个顶点的法向量
                0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, //下面上6个顶点的法向量
        };
    }
}
